package com.czkevin.cif.listeners;

import com.czkevin.cif.BaseBlock;
import com.czkevin.cif.CIFItemInstance;
import com.czkevin.cif.CustomItemFramework;
import com.czkevin.cif.events.CIFBlockChangedEvent;
import com.czkevin.cif.events.CIFBlockEvent;
import org.bukkit.Bukkit;
import org.bukkit.GameMode;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.event.Event;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.block.Action;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.block.BlockExplodeEvent;
import org.bukkit.event.entity.EntityExplodeEvent;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.inventory.ItemStack;

import java.util.List;

public class CIFBasicListener implements Listener {

    @EventHandler(priority = EventPriority.HIGHEST)
    public void onUse(PlayerInteractEvent event) {
        if(event.getAction() != Action.LEFT_CLICK_AIR && event.getAction() != Action.RIGHT_CLICK_AIR && (event.useInteractedBlock() == Event.Result.DENY || event.useItemInHand() == Event.Result.DENY)) return;
        ItemStack used = event.getItem();
        if(used == null) return;
        CIFItemInstance item = CustomItemFramework.getCIFDataFromItem(used);
        if(item == null) return;
        event.setCancelled(true);
        switch(event.getAction()) {
            case RIGHT_CLICK_BLOCK:
                if(item.type.isBlock() && event.getHand() == EquipmentSlot.HAND) {
                    if(item.type.onPlace(item, event)) {
                        Block target = event.getClickedBlock().getRelative(event.getBlockFace());
                        CIFBlockEvent b = new CIFBlockEvent(event.getPlayer(), CIFBlockEvent.Action.PLACE, target.getLocation(), item);
                        Bukkit.getPluginManager().callEvent(b);
                        if(b.isCancelled()) return;
                        ((BaseBlock) item.type).build(event.getPlayer(), target, item);
                        Bukkit.getPluginManager().callEvent(new CIFBlockChangedEvent(event.getPlayer(), CIFBlockEvent.Action.PLACE, target.getLocation(), item)); // broadcast change
                        if(event.getPlayer().getGameMode() != GameMode.CREATIVE) {
                            if(used.getAmount() > 1) {
                                used.setAmount(used.getAmount() - 1);
                            } else {
                                used = null;
                            }
                            if(event.getHand() == EquipmentSlot.HAND) {
                                event.getPlayer().getInventory().setItemInMainHand(used);
                            } else event.getPlayer().getInventory().setItemInOffHand(used);
                        }
                    }
                    break;
                }
            default:
                item.type.onUseInHand(item, event);
                break;
        }
    }

    @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
    public void onBlockBreak(BlockBreakEvent event) {
        Block broken = event.getBlock();
        if(broken.getType() != Material.SPAWNER) return;
        CIFItemInstance item = CustomItemFramework.getCIFDataFromBlock(broken);
        if(item == null) return;

        event.setDropItems(false);
        event.setExpToDrop(0);

        CIFBlockEvent check = new CIFBlockEvent(event.getPlayer(), CIFBlockEvent.Action.BREAK, event.getBlock().getLocation(), item);
        Bukkit.getPluginManager().callEvent(check);
        if(check.isCancelled()) {
            event.setCancelled(true);
            return;
        }

        boolean ok = item.type.onBreak(item, broken, event.getPlayer());
        if(!ok) {
            event.setCancelled(true);
            CustomItemFramework.debug(String.format("Block break cancelled by <%s>. ", item.type.toString()));
        }
        item.type.onBroken(item, event.getBlock(), event.getPlayer());

        Bukkit.getPluginManager().callEvent(new CIFBlockChangedEvent(event.getPlayer(), CIFBlockEvent.Action.BREAK, event.getBlock().getLocation(), item)); // broadcast change
    }

    @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
    public void onExplosion(EntityExplodeEvent event) {
        handleExplosion(event.blockList());
    }
    @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
    public void onExplosion(BlockExplodeEvent event) {
        handleExplosion(event.blockList());
    }

    private void handleExplosion(List<Block> blocks) {
        blocks.removeIf(broken -> {
            CIFItemInstance item = CustomItemFramework.getCIFDataFromBlock(broken);
            if(item == null) return false;
            CIFBlockEvent b = new CIFBlockEvent(null, CIFBlockEvent.Action.BREAK, broken.getLocation(), item);
            Bukkit.getPluginManager().callEvent(b);
            if(b.isCancelled()) {
                return true;
            }
            item.type.onBroken(item, broken, null);
            Bukkit.getPluginManager().callEvent(new CIFBlockChangedEvent(null, CIFBlockEvent.Action.BREAK, broken.getLocation(), item)); // broadcast change
            return false;
        });
    }


    @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
    public void onCIFBlockInteracted(PlayerInteractEvent event) {
        Block clicked = event.getClickedBlock();
        if(clicked == null || clicked.getType() != Material.SPAWNER) return;
        CIFItemInstance item = CustomItemFramework.getCIFDataFromBlock(clicked);
        if(item == null) return;
        CustomItemFramework.debug("TYPE: " + item.type + "Data: \n" + (item.data == null ? "NULL" : item.data.toString()));
        CIFBlockEvent check = new CIFBlockEvent(event.getPlayer(), CIFBlockEvent.Action.USE, clicked.getLocation(), item);
        Bukkit.getPluginManager().callEvent(check);
        if(!check.isCancelled()) {
            item.type.onBlockUse(item, event);
            Bukkit.getPluginManager().callEvent(new CIFBlockChangedEvent(event.getPlayer(), CIFBlockEvent.Action.USE, clicked.getLocation(), item));
        }
    }

}
